/*/////////////////////////////////////////////////////////////////////////////////
/// An
///    ___   ____ ___ _____ ___  ____
///   / _ \ / ___|_ _|_   _/ _ \|  _ \
///  | | | | |  _ | |  | || | | | |_) |
///  | |_| | |_| || |  | || |_| |  _ <
///   \___/ \____|___| |_| \___/|_| \_\
///                              File
///
/// Copyright (c) 2008-2009 Ismail TARIM <ismail@royalspor.com> and the Ogitor Team
///
///This program is free software; you can redistribute it and/or modify it under
///the terms of the GNU Lesser General Public License as published by the Free Software
///Foundation; either version 2 of the License, or (at your option) any later
///version.
///
///This program is distributed in the hope that it will be useful, but WITHOUT
///ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
///FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
///
///You should have received a copy of the GNU Lesser General Public License along with
///this program; if not, write to the Free Software Foundation, Inc., 59 Temple
///Place - Suite 330, Boston, MA 02111-1307, USA, or go to
///http:///www.gnu.org/copyleft/lesser.txt.
///////////////////////////////////////////////////////////////////////////////////*/

/*///////////////////////////////////////////////////////////////////////////////////
/// This Header defines the CBaseEditor class which is the Base Class of All Editor
/// Objects in the Library.
/// This class has both general purpose base functions and also virtual functions
/// for each Editor Object to override in order to create a common framework
/// for different types of editable objects in the scene. It also helps to use the same
/// command for any object regardless of the actual commands needed for the underlying
/// OGRE objects.
///////////////////////////////////////////////////////////////////////////////////*/
#pragma once

namespace Ogitors
{

#if ((OGRE_VERSION_MAJOR * 10) + OGRE_VERSION_MINOR) >= 17
#define DETACHFROMPARENT(a) a->detachFromParent();
#else
#define DETACHFROMPARENT(a) a->detatchFromParent();
#endif

#define DEFINE_PROPERTY(classname,name,desc,type)\
    {\
    OgitorsPropertyDefMap::iterator defi = classname::propertyDefs.find(name);\
    if (defi == classname::propertyDefs.end())\
    {\
    defi = classname::propertyDefs.insert(OgitorsPropertyDefMap::value_type(name, \
    OgitorsPropertyDef(name, desc, type))).first;\
}\
}\

#define DEFINE_REQUIRED_PROPERTIES(classname)\
    {\
    DEFINE_PROPERTY(classname,"name","The name of the object.",PROP_STRING)\
    DEFINE_PROPERTY(classname,"parent","The pointer to parent object.",PROP_UNSIGNED_LONG)\
    DEFINE_PROPERTY(classname,"selected","Is the object selected?.",PROP_BOOL)\
    DEFINE_PROPERTY(classname,"destroyed","Is the object destroyed?.",PROP_BOOL)\
}\

#define IMPLEMENT_PROPERTY(classname, name, type, getter, setter)\
    {\
    OgitorsPropertyDefMap::iterator defi = propertyDefs.find(name);\
    if (defi != propertyDefs.end())\
    {\
    m_Properties.addProperty(\
    new OgitorsProperty<type>(&(defi->second),\
    PropertyGetterFunction<type>::from_method<classname, getter>(this),\
    PropertySetterFunction<type>::from_method<classname, setter>(this)));\
}\
}\

#define IMPLEMENT_REQUIRED_PROPERTIES(classname)\
    {\
    IMPLEMENT_PROPERTY(CBaseEditor, "name", Ogre::String, &classname::getName, &classname::setName)\
    IMPLEMENT_PROPERTY(CBaseEditor, "parent", unsigned long, &classname::getParentLong, &classname::setParentLong)\
    IMPLEMENT_PROPERTY(CBaseEditor, "selected", bool, &classname::getSelected, &classname::setSelected)\
    IMPLEMENT_PROPERTY(CBaseEditor, "destroyed", bool, &classname::getDestroyed, &classname::setDestroyed)\
}\

#define SIGNAL_PROPERTY(propertyname, value)\
    m_Properties.getProperty(propertyname)->signal(Ogre::Any(value));\

#define TRIGGER_POSITION_CHANGE()\
    m_Properties.getProperty("position")->signal(Ogre::Any(m_Position));\

#define TRIGGER_ORIENTATION_CHANGE()\
    m_Properties.getProperty("orientation")->signal(Ogre::Any(m_Orientation));\

#define TRIGGER_SCALE_CHANGE()\
    m_Properties.getProperty("scale")->signal(Ogre::Any(m_Scale));\


#define CONNECT_PROPERTY_MEMFN(object, propertyname, classname, function, connection)\
    object->getProperties()->getProperty(propertyname)->connect(OgitorsSignalFunction::from_method<classname, &classname::function>(this), connection);\

    class OgitorExport CBaseEditor
    {
        friend class CBaseEditorFactory;
    public:
        /**
        * Fetches the factory associated with this object
        * @return factory associated with this object
        */
        static CBaseEditorFactory  *getFactory();
        /**
        * Fetches the factory associated with this object that can be overridden
        * @return factory associated with this object that can be overridden
        */
        virtual CBaseEditorFactory *getFactoryDynamic();
        /**
        * Fetches the unique editor type
        * @return unique editor type
        */
        EDITORTYPE	                getEditorType();
        /**
        * Fetches the unique editor type ID
        * @return unique editor type ID
        */
        unsigned int                getObjectTypeID();
        /**
        * Fetches the corresponding string value of the editor type
        * @return string value of the editor type name
        */
        Ogre::String		        getObjectTypeName();
        /**
        * Fetches a handle to encapsulated object
		* All editor objects represent an underlying object, this function returns that
		* underlying object pointer casted as void *
		* Ex: CCameraEditor returns Ogre::Camera*, CEntityEditor returns Ogre::Entity*
        * @return handle to encapsulated object
        */
        inline virtual void        *getHandle() {return 0;};
        /**
        * Fetches a flag for the bitmask to decide if an editor object has the queried editing option capability
        * @param flags flags to test editor flags against
        * @return true if object has that capability, false otherwise
        */
        bool				        supports(unsigned int flags);
        /**
        * Tests if editor object was modified 
        * @return true if editor object was modified, otherwise false
        */
        inline bool                 isModified() {return m_isModified;};
        /**
        * Sets modified flag for editor object
        * @param bModified new modified flag for editor object
        */
        void                        setModified(bool bModified);
        /**
        * Sets modified flag of object to true, if the parameter passed is true
		* Modified |= bModified;
        * @param bModified new modified flag for editor object
        */
        void                        changeModified(bool bModified);
        /**
        * Tests if editor object uses gizmos
        * @return true if editor object uses gizmos, otherwise false
        */
        inline bool                 usesGizmos() {return m_UsesGizmos;};
        /**
        * Tests if editor object uses visual helper object
        * @return true if editor object uses visual helper object, otherwise false
        */
        inline bool                 usesHelper() {return m_UsesHelper;};
        /**
        * Fetches handle to visual helper object
        * @return handle to visual helper object
        */
        inline CVisualHelper       *getHelper() {return m_Helper;};
        /**
        * Tests if editor object has been loaded
        * @return true if editor object has been loaded, otherwise false
        */
        inline bool                 isLoaded() {return m_isLoaded;};
        /**
        * Tests if oriented bounding box was created for editor object
        * @return true if oriented bounding box was created for editor object, otherwise false
        */
        inline bool                 isBBoxCreated() {return (m_OBBoxRenderable != 0);};
        /**
        * Fetches a handle to the parent of editor object
        * @return a handle to the parent of editor object
        */
        CBaseEditor*                getParent() {return m_Parent;};
        /**
        * Fetches a pointer value to the parent of editor object
        * @return a pointer value to the parent of editor object
        */
        unsigned long               getParentLong() {return (unsigned long)m_Parent;};
        /**
        * Sets new parent for editor object
        * @param newparent new parent
        * @param withundo support undo/redo operation for this action
        */
        void                        changeParent(CBaseEditor *newparent, bool withundo = false);
        /**
        * Sets name for editor object
        * @param name new editor object name
        * @param display flag signifying to refresh the name properties view
        */
        void                        setName(const Ogre::String& name, bool display);
        /**
        * Fetches editor object name
        * @return editor object name
        */
        Ogre::String                getName() {return m_Name;};
        /**
        * Sets locking condition for editor object
        * @param locked lock flag
        * @param display refresh properties view value (unused for this function)
        */
        void                        setLocked(const bool& locked, bool display = false);
        /**
        * Fetches locking condition for editor object
        * @return locking condition for editor object
        */
        bool                        getLocked() {return m_isLocked;};
        /**
        * Fetches editor object properties set
        * @return editor object properties set
        */
        inline OgitorsPropertySet  *getProperties() {return &m_Properties;};
        /**
        * Destroys editor object and cleans up used memory
        * @param informparent flag to inform the parent of this object' destruction
        */
        void                        destroy(bool informparent = false);
        /**
        * Executes assignment of a value for specified binding function
        * @param BIND_ID ID of a function to assign value for
        * @param val value to be assigned
        */
        void	                    executeSetFunction(int BIND_ID,Ogre::String val);
        /**
        * Creates a bounding box for editor object
        */
        void                        createBoundingBox();
        /**
        * Adjusts bounding box after transformation has occured (rotation, translation, scale)
        * @return
        */
        void                        adjustBoundingBox();
        /**
        * Destroys bounding box
        */
        void                        destroyBoundingBox();
        /**
        * Update editor object' treeview properties and make itself selected
        */
        void                        updateTreeView();


        /**
        * Returns a list with object's name and all of its childrens names recursively
        * @param list the list to be filled with names
        */
		void					    getNameList(Ogre::StringVector& list);
        /**
        * Adds a new child object to editor object
        * @param chiled new child object
        */
        void					    addChild(CBaseEditor *child);
        /**
        * Searches for an object amongst parent-child tree with specified name
        * @param name name of the child to search for
        * @param searchchildren if true, search is recursive
        * @return child object handle if found, otherwise 0
        */
        CBaseEditor*			    findChild(Ogre::String name, bool searchchildren);
        /**
        * Destroys all children of an object (recursive)
        */
        void                        destroyAllChildren();
        /**
        * Loads all children object(s) (recursive)
        */
        void                        loadAllChildren();
        /**
        * Unloads all children object(s)
        */
        void                        unLoadAllChildren();
        /**
        * Removes child from children list of editor object (non-recursive)
        * @param name name of child to be removed
        */
        void                        removeChild(Ogre::String name);
        /**
        * Assigns a new parent to all children
        * @param newparent new parent for children
        */
        void                        moveAllChildren(CBaseEditor *newparent);
        /**
        * Fetches a hash map of all children of editor object
        * @return hash map of all children of editor object
        */
        inline NameObjectPairList&  GetChildren() {return m_Children;};
        /**
        * Creates an ordered node object list starting with parents first, children last
        * @param list objects list
        */
        void                        getNodeList(ObjectVector& list);

        /**
        * Reads custom property from an XML element
        * @param element XML element to read property from
        * @return 1 for successfully parsing the property, otherwise 0
        * @remarks should return boolean type
        */
        int                         ReadCustomProperty(TiXmlElement *element);
        /**
        * Adds custom property type
        * @param name name of custom property type (name must be unique)
        * @param type custom property type
        * @return true if custom property type was added successfully, otherwise false
        */
        bool                        AddCustomProperty(Ogre::String name, Ogre::String type);
        /**
        * Adds a new custom property under the group with the given ID; If a group with the given ID can not be found, adds to the root
        * @param id group ID
        * @param name name of custom property type
        * @param type custom property type
        * @return true if custom property type was added successfully, otherwise false
        */
        bool                        AddCustomProperty(unsigned int id, Ogre::String name, Ogre::String type);
        /**
        * Deletes custom property (recursive)
        * @param id property ID
        * @return true if custom property type was deleted successfully, otherwise false
        */
        bool                        DeleteCustomProperty(unsigned int id);
        /**
        * Tests if custom property with specified name exists
        * @param name name of custom property type
        * @return true if such property exists, otherwise false
        */
        bool                        HasCustomProperty(Ogre::String name);
        /**
        * Fills custom properties group of property treeview
        */
        void                        DisplayCustomProperties();
        /**
        * Fetches list of custom properties
        * @return list of custom properties
        */
        CustomPropertyList         *GetCustomPropertyList() {return &m_CustomProperties;};
        /**
        VIRTUAL FUNCTIONS: Overriden By Editor Objects to suit their needs
        **/

        /**
        * Behaviour implementation  when name is changed
        * @param name new editor name
        * @param display to refresh the value in properties view
        */
        virtual void     setNameImpl(Ogre::String name, bool display);
        /**
        * Processes parameters list, initializing the internal properties according to values in the given list
        * @param params parameters list
        */
        virtual void     processParameters(Ogre::NameValuePairList &params) {};
        /**
        * General purpose update function used by OgitorsRoot @see OgitorsRoot::Update
        * @param timePassed delta of time
        * @return true if update modified the scene, otherwise false
        */
        virtual bool     update(float timePassed) {return false;};
        /**
        * General purpose update function used by OgitorsRoot
        * @param SceneMngr scene manager handle
        * @param Camera camera handle
        * @param RenderWindow render window handle
        * @return must always return false
        * @remarks the return value may be used in the future
        */
        virtual bool     postSceneUpdate(Ogre::SceneManager *SceneMngr, Ogre::Camera *Camera, Ogre::RenderWindow *RenderWindow) {return false;};
        /**
        * Creates editor object
        * @return true if this object is successfully, otherwise false (also forces object's parent to load too)
        */
        virtual bool     load() {m_isLoaded = true;return true;};
        /**
        * Unloads editor object and all of its children
        * @return false if editor was not loaded properly, otherwise true
        */
        virtual bool     unLoad() {unLoadAllChildren();m_isLoaded = false;return true;};
        /**
        * Writes custom files during an export procedure
        */
        virtual void     onSave() {};
        /**
        * Sets up and displays properties in the PropertyGrid
        * @param present if true, prepares and fills properties into PropertyGrid
        * @return true if successfull, otherwise false
        */
        virtual bool	 setupPropertiesWnd(bool present);
        /**
        * Shows or hides editor' bounding box
        * @param bShow flag to signify whether to show or hide bounding box
        */
        virtual void     showBoundingBox(bool bShow);
        /**
        * Highlights editor object
        * @param highlight flag to signify whether to highlight selected object or not
        */
        virtual void     highlightObject(bool highlight);
        /**
        * Assigns a visual helper for a objects without mass (Light or camera, for example)
        * @param objHelper helper object
        */
        virtual void	 setHelper(CVisualHelper *objHelper);
        /**
        * Shows or hides helper object
        * @param show flag to signify whether to hide or show helper object
        */
        virtual void     showHelper(bool show);
        /**
        * Implementation for selecting an object
        * @param bSelected flag to signify if object is selected or not
        */
        virtual void     setSelectedImpl(bool bSelected);
        /**
        * Sets an object selection flag
        * @param bSelected flag to signify if object is selected or not
        * @param display to refresh the value in properties view
        */
        void             setSelected(const bool& bSelected, bool display = false);
        /**
        * Tests if any object is selected
        * @return true if this object is selected, otherwise false
        */
        bool             getSelected();
        /**
        * Tests if editor object is destroyed
        * @return true if editor object is destroyed, otherwise false
        * @remarks this is a dummy function used as a getter for "destroyed" property
		*/
        bool             getDestroyed() {return false;};
        /**
        * Fetches context-based properties menu for specified property type 
        * @param itemid property type
        * @param menuitems menu entries for the property
        * @return true if any properties were returned, otherwise false
        */
        virtual bool             getPropertyContextMenu(unsigned int itemid, UTFStringVector &menuitems) {menuitems.clear();return false;};
        /**
        * Delegate function that is called when menu entry for context-based properties menu is selected
        * @param itemid property type
        * @param menuresult menu entry index
        */
        virtual void             onPropertyContextMenu(unsigned int itemid, int menuresult) {};
        /**
        * Fetches a context-based object menu (right-click on the scene)
        * @param menuitem menu items the menu contains
        * @return true if menu has entries, otherwise false
        */
        virtual bool             getObjectContextMenu(UTFStringVector &menuitems) {menuitems.clear();return false;};
        /**
        * Delegate function that is called when an object is selected in objects context menu
        * @param menuresult result of menu selection
        */
        virtual void             onObjectContextMenu(int menuresult) {};
        /**
        * Delegate function that is called when material is dropped onto the scene
        * @param position position of where it is dropped on
        * @param materialname name of the material being dropped
        */
        virtual void             onDropMaterial(Ogre::Vector3 position, const Ogre::String& materialname) {};
        /**
        * Stores Object's properties as a NameValuePairList
        * @param retList container into which to put object properties
        */
        virtual void             getObjectProperties(Ogre::NameValuePairList &retList);
        /**
        * Fetches data binded to undo/redo operation
        * @param undotype type of the undo/redo operation
        * @return undo/redo operation data
        */
        virtual OGITORUNDOSTRUCT getUndoData(OGITORUNDOTYPE undotype);
        /**
        * Restores object's property set to given value(s)
        * @param retList properties list to restore
        */
        virtual void            restore(Ogre::NameValuePairList &retList);
        /**
        * Restores custom properties list to previous value(s)
        * @param theList custom properties list to restore
        */
        virtual void            restoreCustomProperties(CustomPropertyList &theList);
        /**
        * Saves custom properties to output stream
        * @param outstream output stream to save custom properties to
        * @param indent indentation amount
        */
        void                    saveCustomPropertiesToStream(std::ostream &outstream,int indent);
        /**
        * Tests if editor object is serializable
        * @return true if editor object is serializable, otherwise false
        * @remarks Some objects may be temporary and should not be stored in project file
		*/
        virtual bool            isSerializable() {return true;};
        /**
        * Tests if editor object is of node type (Overriden by editor class if it has node capabilities)
        * @return true if editor object has node capabilities, otherwise false
        */
        virtual bool            isNodeType() {return false;};
        /**
        * Tests if editor object is of terrain type (Overriden by editor class if it has terrain capabilities)
        * @return true if editor object has terrain capabilities, otherwise false
        */
        virtual bool            isTerrainType() {return false;};
        /**
        * Fetches terrain editor associated with editor object
        * @return terrain editor associated with editor object
        */
        virtual CTerrainEditor* getTerrainEditor() {return 0;};
        /**
        * Delegate function that is called when terrain editor associated with editor object is destroyed
        * @return true when destruction procedure is completed successfully, otherwise false
        */
        virtual bool            onTerrainDestroyed() {return false;};

        /// VARIOUS GETXXX FUNCTIONS OVERRIDEN BY EDITOR OBJECTS TO STANDARDIZE
        /// PROPERTY RETRIEVAL FROM UNDERLYING OGRE OBJECTS

        /**
        * Fetches node handle associated with editor object
        * @return node handle associated with editor object, if none returns 0
		* @remarks the default behavior is to fetch object's parent's node if object has a parent
        */
        virtual Ogre::SceneNode     *getNode() {if(m_Parent) return m_Parent->getNode(); else return 0;};
        /**
        * Fetches scene manager handle associated with editor object
        * @return scene manager handle associated with editor object, if none returns 0
        */
        virtual Ogre::SceneManager  *getSceneManager() {if(m_Parent) return m_Parent->getSceneManager(); else return 0;};
        /**
        * Fetches editor object' DERIVED position
        * @return editor object' DERIVED position
        */
        virtual Ogre::Vector3	     getDerivedPosition() {return Ogre::Vector3(0,0,0);}
        /**
        * Fetches editor object' DERIVED orientation
        * @return editor object' DERIVED orientation
        */
        virtual Ogre::Quaternion     getDerivedOrientation() {return Ogre::Quaternion::IDENTITY;};
        /**
        * Fetches editor object' DERIVED scale
        * @return editor object' DERIVED scale
        */
        virtual Ogre::Vector3        getDerivedScale() {return Ogre::Vector3(1,1,1);};
        /**
        * Fetches axis aligned bounding box associated with editor object
        * @return axis aligned bounding box associated with editor object
        */
        virtual Ogre::AxisAlignedBox getAABB() {return Ogre::AxisAlignedBox::BOX_NULL;};
        /**
        * Sets editor object' DERIVED position
        * @param val new editor object' DERIVED position
        */    
        virtual void			     setDerivedPosition(Ogre::Vector3 val);
        /**
        * Sets editor object' DERIVED orientation
        * @param val new editor object' DERIVED orientation
        */    
        virtual void			     setDerivedOrientation(Ogre::Quaternion val);
        /**
        * Fetches void-based treeview item handle @see OgitorsSystem::InsertTreeItem
        * @return treeview item handle
        */
        inline void                 *getTreeItemHandle() {return m_TreeItemHandle;};
        /**
        * Sets treeview item handle to specified value
        * @param handle handle for treeview item
        */
        inline void                  setTreeItemHandle(void * handle) {m_TreeItemHandle = handle;};

    protected:
        static bool             m_Initialised;                  /** Flag signifying that static initialization was completed */ 
        static OgitorsSystem   *m_System;                       /** Global OgitorsSystem handle */ 
        static OgitorsPhysics  *m_Physics;                      /** Global OgitorsPhysics handle */ 

        bool                    m_isLoaded;                     /** Flag signifying if editor object was successfully created and loaded */ 
        CBaseEditor			   *m_Parent;                       /** Parent handle */
        Ogre::String            m_Name;                         /** A copy of editor object's name to register/unregister when object destroyed by scene manager and we cant rely on GetName() */
        bool				    m_UsesHelper;                   /** A flag signifying that editor uses visual helper object */
        bool                    m_UsesGizmos;                   /** A flag signifying  that editor object uses gizmos when selected*/
        bool                    m_isSelected;                   /** Flag signifying if editor object is selected*/
        bool                    m_isHighLighted;                /** Flag signifying that editor object is highlighted */
        bool				    m_isLocked;                     /** Flag signifying if this object is locked */
        bool                    m_isModified;                   /** Flag signifying if editor object was modified */
        NameObjectPairList      m_Children;                     /** Hash map of children object(s)*/
        CustomPropertyList      m_CustomProperties;             /** List of object's custom properties */
        unsigned int            m_CustomPropertyIDs;            /** A counter to assign unique IDs to custom properties*/
        CVisualHelper		   *m_Helper;                       /** Visual helper object handle */
        Ogre::SceneNode        *m_BoxParentNode;                /** Custom bounding box' parent node */
        Ogre::SceneNode        *m_BBoxNode;                     /** Custom bounding Box node */
        Ogre::SceneNode        *m_HighlightNode;                /** Selection bounding box node */
        OBBoxRenderable*        m_OBBoxRenderable;              /** Custom bounding box handle */
        OBBoxRenderable*        m_HighlightRenderable;          /** Custom selection box handle */
        Ogre::AxisAlignedBox    m_OBBoxData;                    /** A copy of previos AABB size */
        OgitorsPropertySet      m_Properties;                   /** Editor properties list */
        void                   *m_TreeItemHandle;               /** Treeview item handle */

        /**
        * Constructor
        */
        CBaseEditor();
        /**
        * Destructor
        */
        virtual                ~CBaseEditor();

        /** Used by ChangeParent to attach underlying helper objects */
        virtual void            attach(CBaseEditor *parent);

        /** Used by ChangeParent to detach underlying helper objects */
        virtual void            detach();

        /**
        * Recreates binding IDs for newly added custom property
        * @param prop new custom property that was added
        * @param PARENTID parent for newly created custom property
        */
        void                    RecurseCreateIDs(CUSTOMPROPERTY *prop, unsigned int PARENTID);

        /**
        * Searches and displays child(ren) of a custom property (Recursive)
        * @param prop property to display child(ren) for
        */
        void                    RecurseDisplayCustomProperty(CUSTOMPROPERTY *prop);

        /**
        * Searches and saves child(ren) of a custom property to output stream
        * @param outstream output stream to which is to save child(ren) properties
        * @param indent indentation amount
        * @param p property to save child(ren) of
        */
        void                    RecurseSaveCustomPropertiesToStream(std::ostream &outstream,int indent, CUSTOMPROPERTY *p);

        /// Recursively searches and tries to find a custom property with the ID specified
        CUSTOMPROPERTY         *FindCustomProperty(unsigned int ID, CUSTOMPROPERTY *prop);

        /// Sets the value of a custom property with the BIND_ID as ID
        /// Called when a Changed message recevied from Property List Window
        bool                    HandleCustomProperty(int BIND_ID,Ogre::String val);

        /// Validates the new value according to lower/upper bounds
        void                    CheckCustomPropertyBounds(CUSTOMPROPERTY *prop, Ogre::String &val);

        /**
        * If property ID is more than MAXIMUM_BINDING_FUNCTIONS then it is a custom function. If so, each object' handleCustomFunction() function is called
        to handle editor specific custom functions which are not defined in PROPERTYBINDINGS
        * @param BIND_ID property binding ID
        * @param val property value
        * @return true if property notification was handled, otherwise false
        */
        virtual bool            handleCustomFunction(int BIND_ID,Ogre::String val) {return true;};

        /**
        * Utility function convert a unsigned long PF_BGRA string to Ogre::Vector3 colour
        * @param val unsigned long string 
        * @return Ogre::Colour3-based colour value
        */
        Ogre::ColourValue       convertColour(Ogre::String &val);

        /**
        * Registers editor object name in the system
        */
        void                    registerObjectName();
        /**
        * Unregisters editor object name in the system
        */
        void                    unRegisterObjectName();
        /**
        * Registers editor object for update notifications
        */
        void                    registerForUpdates();
        /**
        * Unregisters editor object from update notifications
        */
        void                    unRegisterForUpdates();
        /**
        * Registers editor object for a single update after the scene is loaded
        */
        void                    registerForPostSceneUpdates();

        /**
        * Sets new parent for editor object
        * @param newparent unsigned long pointer value to new parent
        * @param display display parent' change in treeview
        */
        void		            setParentLong(const unsigned long& newparent, bool display) {m_Parent = (CBaseEditor*)newparent;};
        /**
        * Sets destruction flag before calling Destroy()
        * @param destroy return result of object destruction
        * @param display display changes in treeview
        */
        void                    setDestroyed(const bool& destroy, bool display = true);
    };

    //! Base editor factory class
    /*!  
    A class that is responsible for instantiating base editor class(es)
    */
    class OgitorExport CBaseEditorFactory
    {
    public:
		unsigned int mTypeID;            /** Unique type identifier (Internal Use) */
        Ogre::String mTypeName;          /** Unique type name. Set in call to OgitorsRoot::RegisterEditorObjectFactory (Internal Use) */
        EDITORTYPE   mEditorType;        /** Type of editor objects created by this factory */
        Ogre::String mPropertySheet;     /** The relative path to the property sheet of editor objects created by this factory */
        bool         mAddToObjectList;   /** If set to true, editor objects created by this factory will be displayed in Add Objects Menu/Toolbar */
        bool         mRequirePlacement;  /** If true, will allow placement of editor objects created by this factory onto the scene with left mouse click */
        Ogre::String mIcon;              /** Path to SVG Icon for editor objects created by this factory */
        unsigned int mCapabilities;      /** The capabilities supported by the editor objects created by this factory */
        int          mInstanceCount;      /** Number of base editor objects instantiated */
 
		OgitorsPropertyDefMap mPropertyDefs; /** Class holding all static property definition data */
		

        /**
        * Constructor
        */
        CBaseEditorFactory();
        /**
        * Destructor
        */
        virtual ~CBaseEditorFactory() {};
        /**
        * Initialization procedure
        */
        virtual void Init() {};
        /**
        * Returns the type name of this factory
        */
        Ogre::String getTypeName() {return mTypeName;};
        /**
        * Creates editor object
        * @param parent parent for editor object
        * @param params additional instantiation parameters
        * @return newly created editor object on success, otherwise 0
		* @remarks the object may modify the parent parameter (Some objects may prefer to be parented by some other fixed object)
        */
        virtual CBaseEditor *CreateObject(CBaseEditor **parent, Ogre::NameValuePairList &params);
        /**
        * Clones editor object
        * @param parent parent for editor object
        * @param object editor object that is to be cloned
        * @return cloned editor object on success, otherwise 0
        */
        virtual CBaseEditor *CloneObject(CBaseEditor **parent, CBaseEditor *object);
        /**
        * Destroys editor object
        * @param object editor object to be destroyed
        */
        virtual void DestroyObject(CBaseEditor *object);
        /**
        * Tests if another editor object instance can be created
        * @return true if another editor object instance can be created, otherwise false
        */
        virtual bool CanInstantiate() {return true;};
        /**
        * Fetches placeholder Mesh Name, to visualize the object during a 3D Drag'n'Drop
        * @return name of placeholder
        */
        virtual Ogre::String GetPlaceHolderName() {return "";};
        /**
        * Adds a new property definition
        * @param name Name of the property to be added
        * @param desc Description of the property to be added
		* @param pType Type ID of the property
		* @param read can this property's value be read? (if not, it wont be displayed in properties view)
		* @param write can this property's value be changed? (if not, it becomes read-only in properties view)
        * @return Returns a pointer to the new property definition
		*/
		OgitorsPropertyDef *AddPropertyDefinition(const Ogre::String& name, const Ogre::String& desc, OgitorsPropertyType pType, bool read = true, bool write = true);
    };
}
